module Libp2p.Mux.Types (
    StreamState(..),
    Stream(..),
    Session(..),
    StreamMessage(..),
    SessionMainMessage(..)
) where
import qualified Data.ByteString as BS
import Control.Concurrent.STM.TVar
import Control.Concurrent.STM.TMVar
import Control.Concurrent.MVar
import Control.Concurrent.STM.TChan
import qualified Control.Concurrent.STM.TBQueue as TB
import Libp2p.Mux.Config
import Libp2p.Mux.Const
import Network.Socket
import qualified Control.Concurrent.Actor as Act
import Data.Map
import Data.Word
import qualified System.Log.FastLogger as Log
import Data.IORef
import Data.Time.Clock
import qualified Network.Socket as NS

data StreamState = StreamInit | StreamSYNSent | StreamSYNReceived | StreamEstablished 
                  | StreamLocalClose |  StreamRemoteClose | StreamClosed | StreamReset deriving (Eq,Show)

data StreamMessage = SendWindowUpdate (MVar (Maybe String)) | IncrSendWindow Header (MVar (Maybe String))
                    | ReadToBuffer Header BS.ByteString deriving (Eq)

data Stream = Stream {
  sess::Session,
  streamId::Integer,
  recvWindow::TVar Int,
  sendWindow::TVar Int,
  streamState::TVar StreamState,
  recvBuf::TVar BS.ByteString,
  streamActor::TVar (Maybe (Act.Actor StreamMessage)),
  sendNotifyCh::TMVar (),
  recvNotifyCh::TMVar ()
}

data SessionMainMessage = OpenStream (MVar (Either String Stream)) 
                          | HandlerWindowUpdate　Header
                          | GoAway Int | HandlerGoAway Int
                          | SendStreamEstablished Int
                          | CloseStream Int
                          | HandlerReadData Header BS.ByteString
                          | CloseSession
                          | GetStreamLength (TMVar Int) deriving (Eq)

data Session = Session {
  config::Config,
  conn::Socket,
  pings::IORef (Map Int UTCTime),
  pingID::IORef Int,
  recvActor::TVar (Maybe (Act.Actor String)),
  mainActor::TVar (Maybe (Act.Actor SessionMainMessage)),
  sendChannel::TChan BS.ByteString,
  shutdownCh::TMVar (),
  isShutdown::TVar Bool,
  shutdownErr::TVar String,
  log::Log.FastLogger,
  streams::IORef (Map Integer Stream),
  remoteGoAway::IORef Bool,
  localGoAway::IORef Bool,
  nextStreamID::IORef Integer,
  synCh::TB.TBQueue (),
  acceptCh::TB.TBQueue Stream,
  inflight::IORef (Map Integer ()),
  isClient::Bool,
  recvDownCh::TMVar (),
  sendDownCh::TMVar ()
}